<?php
/**
 * Application configuration file
 *
 * @author v@kamenskiy.biz
 * @package Hydrum
 */
class Hydrum_Application_Config extends Zend_Config_Xml
{

    public function __construct($host)
    {
        $configs = $this->getConfigsDocuments();

        $code = $this->getCode($configs, $host);

        if (!$code) {
            throw new Exception("Can't find application by host " . $host);
        }

        $xml = $this->prepareConfigsXML($configs);

        parent::__construct($xml, $code, true);
    }
    
    /**
     * Get currently loaded application
     * 
     * @return string
     */
    public function getApplicationPath()
    {
        $paths = $this->applications->toArray();
        
        return end($paths);
    }

    /**
     * Return application code by host
     *
     * @param DOMDocument $configs
     * @param string $host
     * @return string
     */
    protected function getCode($configs, $host)
    {
        $code = null;

        $xpath = new DOMXPath($configs);

        $entries = $xpath->query("/applications/*[@host='" . $host . "']");

        if ($entries->length > 0) {
            $code = $entries->item(0)->tagName;
        }

        return $code;
    }

    /**
     * Return constant value
     *
     * @param array $matches
     * @return mixed|null
     */
    protected function matchConstant($matches)
    {
        if (defined($matches[1])) {
            return constant($matches[1]);
        } else {
            return $matches[0];
        }
    }

    /**
     * Return configs XML with replace constances
     *
     * @param DOMDocument $configs
     * @return string
     */
    protected function prepareConfigsXML(DOMDocument $configs)
    {
        $xml = $configs->saveXML();

        return preg_replace_callback("/\{\\$([^\}]*)\}/", array($this, 'matchConstant'), $xml);
    }

    /**
     * Return DOM document which contains all applications configs
     *
     * @return DOMDocument
     */
    protected function getConfigsDocuments()
    {
        $configs = new DOMDocument();
        $configs->loadXML('<applications/>');

        $directory = new DirectoryIterator(APPLICATIONS_PATH);

        foreach ($directory as $entry) {
            $entryName = $entry->getFilename();

            if ($entry->isDot() || !$entry->isDir() || preg_match('/^[^a-z]/i', $entryName))
                continue;

            $path = $entry->getPathname() . DS . 'configs' . DS . 'application.xml';

            $config = $this->getConfigDocument($path);

            if ($config) {
                $node = $configs->importNode($config->documentElement, true);

                $configs->documentElement->appendChild($node);
            }
        }

        return $configs;
    }

    /**
     * Return DOM document which contains application config
     *
     * @param string $path
     * @return DOMDocument
     */
    protected function getConfigDocument($path)
    {
        $config = null;

        if (file_exists($path)) {
            $config = new DOMDocument();

            $config->load($path);

            $rootNode = $config->documentElement;

            $applicationsNode = $config->createElement('applications');

            $rootNode->appendChild($applicationsNode);

            $applicationPath = realpath(dirname($path) . '/../');

            $codeNode = $config->createElement($rootNode->tagName, $applicationPath);

            $applicationsNode->appendChild($codeNode);
        }

        return $config;
    }
}
